package cd.cdyb.sms.service.impl;

import cd.cdyb.sms.dao.SignatureDao;
import cd.cdyb.sms.dao.TemplateDao;
import cd.cdyb.sms.domain.Signature;
import cd.cdyb.sms.domain.Template;
import cd.cdyb.sms.dto.PageResult;
import cd.cdyb.sms.dto.TemplateDto;
import cd.cdyb.sms.dto.expand.ExTemplateDto;
import cd.cdyb.sms.dto.query.QueryTemplateDto;
import cd.cdyb.sms.exception.BusinessException;
import cd.cdyb.sms.service.RedisService;
import cd.cdyb.sms.service.TemplateService;
import cd.cdyb.sms.utils.BeanUtilPlus;
import cd.cdyb.sms.utils.CacheUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author: lilin
 * @CreateTime: 2024-05-14  16:02
 * @Description: 模板
 */
@Service
public class TemplateServiceImpl implements TemplateService {

    @Resource
    private TemplateDao templateDao;

    @Resource
    private RestTemplate restTemplate;

    @Value("${sms.url}")
    private String url;

    @Value("${sms.appid}")
    private String appid;

    @Value("${sms.appKey}")
    private String appKey;

    @Resource
    private SignatureDao signatureDao;

    @Resource
    private RedisService redisService;

    @Override
    public void insertSignature(TemplateDto templateDto) throws BusinessException {
        Signature signature = signatureDao.selectById(templateDto.getSignatureId());
        if (Objects.isNull(signature)) {
            throw new BusinessException("签名不能为空");
        }
        templateDto.setContent(signature.getName() + templateDto.getContent());
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            Map<String, Object> requestParams = createInsertRequestParams(appid, appKey, templateDto);
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestParams, headers);
            ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url + "/send/textTemplateSignatureReport", requestEntity, JSONObject.class);
            HttpStatus statusCode = responseEntity.getStatusCode();
            if (statusCode == HttpStatus.OK) {
                JSONObject responseBody = responseEntity.getBody();
                if (Objects.isNull(responseBody)) {
                    throw new BusinessException("模板申请失败，请重试");
                }
                String code = responseBody.getString("code");
                String templateId = responseBody.getString("template_id");
                if (!"200".equals(code) || StringUtils.isBlank(templateId)) {
                    throw new BusinessException("模板申请失败，请重试,code=" + code);
                }
                Template template = BeanUtilPlus.copyAs(templateDto, Template.class);
                template.setStatus(1);
                template.setNumber(templateId);
                templateDao.insert(template);
            } else {
                throw new BusinessException("第三方请求失败，请重试");
            }
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }

    }

    @Override
    public PageResult<ExTemplateDto> findTemplatePage(QueryTemplateDto queryTemplateDto) {
        Page<Template> page = new Page<>(queryTemplateDto.getPageNo(), queryTemplateDto.getPageSize());
        IPage<ExTemplateDto> iPage = templateDao.findTemplatePage(queryTemplateDto, page);
        List<ExTemplateDto> templateList = iPage.getRecords();
        if (!CollectionUtils.isEmpty(templateList)) {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            Map<String, Object> requestParams = getRequestParams();
            templateList.stream()
                    .filter(temp -> temp.getStatus() == 1)
                    .forEach(temp -> {
                        requestParams.put("template_id", temp.getNumber());
                        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestParams, headers);
                        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url + "/send/getTemplateForApi", requestEntity, JSONObject.class);
                        JSONObject body = responseEntity.getBody();
                        if (responseEntity.getStatusCode() != HttpStatus.OK || Objects.isNull(body)) {
                            return;
                        }
                        String code = body.getString("code");
                        JSONObject template = body.getJSONObject("template");
                        if (!"200".equals(code) || Objects.isNull(template)) {
                            return;
                        }
                        Integer status = template.getInteger("status");
                        Integer variableLen = template.getInteger("variable_len");
                        if (Objects.nonNull(status) && Objects.nonNull(variableLen)) {
                            LambdaUpdateWrapper<Template> updateWrapper = new LambdaUpdateWrapper<>();
                            updateWrapper.set(Template::getStatus, status)
                                    .set(Template::getVariableLen, variableLen)
                                    .eq(Template::getTemplateId, temp.getTemplateId());
                            templateDao.update(null, updateWrapper);
                        }
                    });
            iPage = templateDao.findTemplatePage(queryTemplateDto, page);
        }
        return new PageResult<>(queryTemplateDto.getPageNo(), queryTemplateDto.getPageSize(), iPage.getRecords(), iPage.getTotal());
    }

    @Override
    public ExTemplateDto getTemplateById(Integer templateId) throws BusinessException {
        ExTemplateDto exTemplateDto = templateDao.getTemplateById(templateId);
        if (Objects.isNull(exTemplateDto)) {
            throw new BusinessException("未查询到该模板");
        }
        if (1 == exTemplateDto.getStatus()) {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            Map<String, Object> requestParams = getRequestParams();
            requestParams.put("template_id", exTemplateDto.getNumber());
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestParams, headers);
            ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url + "/send/getTemplateForApi", requestEntity, JSONObject.class);
            JSONObject body = responseEntity.getBody();
            if (responseEntity.getStatusCode() == HttpStatus.OK && Objects.nonNull(body)) {
                String code = body.getString("code");
                JSONObject template = body.getJSONObject("template");
                if ("200".equals(code) && Objects.nonNull(template)) {
                    Integer status = template.getInteger("status");
                    if (Objects.nonNull(status)) {
                        LambdaUpdateWrapper<Template> updateWrapper = new LambdaUpdateWrapper<>();
                        updateWrapper.set(Template::getStatus, status)
                                .eq(Template::getTemplateId, exTemplateDto.getTemplateId());
                        templateDao.update(null, updateWrapper);
                        exTemplateDto = templateDao.getTemplateById(templateId);
                    }
                }
            }
        }
        return exTemplateDto;
    }

    @Override
    public String getCacheTemplateById(String templateId)  {
        String content = (String) redisService.vGet(CacheUtils.CacheName.SMS_TEMPLATE, templateId);
        if (StringUtils.isBlank(content)) {
            ExTemplateDto exTemplateDto = templateDao.getTemplateByNumber(templateId);
            content = exTemplateDto.getContent();
            redisService.vPut(CacheUtils.CacheName.SMS_TEMPLATE, templateId, content);
        }
        return content;
    }

    @Override
    public Map<String, Long> indexTemplateStatisticsWithClient(Integer companyId) {
        HashMap<String, Long> map = new HashMap<>();
        map.put("wait", 0L);
        map.put("deactivated", 0L);
        map.put("pass", 0L);
        map.put("fail", 0L);
        LambdaQueryWrapper<Template> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(Template::getStatus)
                .eq(Template::getCompanyId, companyId);
        List<Template> templateList = templateDao.selectList(wrapper);
        Map<Integer, Long> statusCountMap = templateList.stream()
                .collect(Collectors.groupingBy(Template::getStatus, Collectors.counting()));
        statusCountMap.forEach((status, count) -> {
            if (1 == status) {
                map.put("wait", count);
            }
            if (2 == status) {
                map.put("deactivated", count);
            }
            if (3 == status) {
                map.put("pass", count);
            }
            if (4 == status) {
                map.put("fail", count);
            }
        });
        return map;
    }

    @NotNull
    private Map<String, Object> getRequestParams() {
        Map<String, Object> requestParams = new HashMap<>();
        requestParams.put("appid", appid);
        requestParams.put("appkey", appKey);
        requestParams.put("template_type", 1);
        return requestParams;
    }

    private Map<String, Object> createInsertRequestParams(String appid, String appKey, TemplateDto templateDto) {
        Map<String, Object> requestParams = new HashMap<>();
        requestParams.put("appid", appid);
        requestParams.put("appkey", appKey);
        requestParams.put("title", templateDto.getName());
        requestParams.put("connect", templateDto.getContent());
        requestParams.put("type", templateDto.getType());
        return requestParams;
    }
}
